Skip to content

feat(libc): wire the codecvt<wchar_t,char> facet vtable - #11172

Open
00xDisaster wants to merge 5 commits into
boykopovar:mainfrom
00xDisaster:feat/libc-codecvt-wide-vtable
Open

00xDisaster wants to merge 5 commits into
boykopovar:mainfrom
00xDisaster:feat/libc-codecvt-wide-vtable

Conversation

@00xDisaster

@00xDisaster 00xDisaster commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

What

Wire the exported codecvt<wchar_t,char,_Mbstatet> vtable. #10180 added the thirteen-slot _ZTVSt7codecvtIwc9_MbstatetE_nid_postfix data object (NID H-TDszhsYuY, st_size 104) with every slot zero, so a title that resolved the object and called in, out or unshift faulted. Slots 2 through 11 now hold the same facet methods and conversion virtuals that the console uses; slot 12 (length) throws.

The slot order and the conversion behaviour come from the libc.prx bundled with PPSA03446; the size and facet layout were already recorded from PPSA26344 and libSceLibcInternal.sprx. Slots 2 to 5 are the facet destructor, deleting destructor, retain and release; slot 6 returns false for always_noconv; slot 7 returns 6 for max_length; slot 8 returns 0 for encoding; slots 9 to 12 are in, out, unshift and length. The console's in and out delegate to its _Mbtowcx and _Wctombx, so this port does the same through the guest UTF-8 helpers: in decodes one- to three-byte UTF-8, out encodes one to three bytes, four-byte leads are invalid, a partial output buffer returns partial, an invalid sequence returns error, and unshift clears the state.

The length slot throws instead of returning a character count. Standard do_length consumes input bytes rather than wide characters, and no disassembly or console run established this module's return value or its state effect, so the slot stays unsupported until that evidence exists. The debt entry records the gap.

_Mbtowcx and _Wctombx previously used the host mbrtowc/wcrtomb, which depends on the host C locale and cannot produce the guest's three-byte UTF-8. They now use the guest helpers, and _Getpmbstate and _Getpwcstate reserve the 16-byte conversion state those helpers read and write. Slots 0 and 1 remain zero, as they were; the debt entry records that and the console's relocated offset-to-top and typeinfo entries.

This does not change the narrow codecvt<char> object in #10165, the num_put work in #11054, the collate<char> object in #11166, or the fgetwc surrogate handling in #10929, and no open PR implements these wide conversion virtuals. The only overlap is textual: #10165 resizes and moves the adjacent narrow codecvt declaration, so whichever lands second needs a rebase; this PR is listed after #10165 so the older change can land first.

Tested

Linux CachyOS 7.3.0-4-cachyos, GCC 16.2.1. Base upstream/main 0836dfdf4fecb1e0326100c490476e15d3a74da5; head 597258ffad.

  • cmake --build build --target guest_locale_tests guest_multibyte_locale_tests guest_wide_conversion_tests guest_wide_formatting_tests guest_wide_string_tests guest_wide_stream_scan_tests --parallel: passed.
  • ctest --test-dir build -R '^(guest_locale|guest_multibyte_locale|guest_wide_formatting|guest_wide_strings|guest_wide_conversion|guest_wide_stream_scan)$' --output-on-failure: 6/6 passed after the rebase.
  • guest_locale calls the exported vtable's in, out and unshift, checks ASCII, two- and three-byte UTF-8, an incomplete lead completed by the next call, a partial output buffer, an invalid four-byte lead, the facet retain/release slots, and that slots 0 and 1 stay zero. It calls length and asserts that it throws.
  • tools/check_conventions.py --base upstream/main --head HEAD and git diff --check upstream/main..HEAD: clean.
  • The two macOS write-watch jobs fail before building this PR: core/libs/tests/write_watch/CMakeLists.txt registers write_watch_execute-fault and write_watch_read-fault twice. The same duplicate loop is present on upstream/main; this PR does not touch that file, so it is a base-branch CI issue rather than an effect of this change.
  • Windows 11 26300, WinLibs GCC 15.2.0, Release (maskym, independent run on an earlier head): build clean; guest_locale passed in a joint 160/160 run of the libc, CesCs, Font, FreeType, LibreSsl3 and NpUniversalDataSystem suites. That run predates the refresh; the refreshed head is tested on Linux above. Not run on a PS5.
  • GPUs tested: n/a.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: no

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Progress report (0278ca9 → d7562dc)

📈 System libraries: 26.19% (+0.02%, +7 implemented functions)

✅ 7 implemented
Library Name
libc WideCodecvtAlwaysNoconv
libc WideCodecvtEncoding
libc WideCodecvtIn
libc WideCodecvtLength
libc WideCodecvtMaxLength
libc WideCodecvtOut
libc WideCodecvtUnshift
⚪ 4 behaviourally empty (constant return or throw)
Library Name
libc WideCodecvtAlwaysNoconv
libc WideCodecvtEncoding
libc WideCodecvtLength
libc WideCodecvtMaxLength

Changed libraries (implemented exports)

Library Before After Change
libc 1530/1548 (98.84%) 1537/1555 (98.84%) +0.01%

@00xDisaster
00xDisaster force-pushed the feat/libc-codecvt-wide-vtable branch from e0d580e to 6ad55bf Compare October 25, 2026 20:40

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed head 6ad55bff263cb8a47ce17a2c9391b9eacc4bfbba, including the wide facet slot layout, UTF-8 conversion loops, partial-input continuation, output buffer handling, and the 16-byte guest conversion-state storage. The new tests exercise the vtable and the relevant one-, two-, and three-byte cases. I did not find a concrete correctness issue in the reviewed changes.

Independent checks here: C++20 syntax compilation of LocaleSupport.cpp and GuestLocale.cpp, plus git diff --check upstream/main...HEAD, passed. The author reports the six focused locale suites passed. Hosted conventions, labels, and report checks now pass; I do not see hosted product-build results on this head. I’m leaving a comment-only review pending runtime/build evidence rather than approving without it.

@00xDisaster

00xDisaster commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Local build evidence at 6ad55bff263cb8a47ce17a2c9391b9eacc4bfbba:

  • cmake --build build --target relinker — built successfully (Release, Ninja).
  • ctest --test-dir build -R '^(relinker_conversion|relinker_game_patch|relinker_executables)$' --output-on-failure — 3/3 passed.
  • ctest --test-dir build -R '^(guest_locale|guest_multibyte_locale|guest_wide_formatting|guest_wide_strings|guest_wide_conversion|guest_wide_stream_scan)$' — 6/6 passed; guest_locale also passed 100 repeated runs.
  • Local ASan build (ANYPS5_ENABLE_ASAN=ON) of libc and guest_locale_tests — built successfully and guest_locale passed, including the 16-byte _Getpmbstate/_Getpwcstate paths.
  • tools/check_conventions.py --base upstream/main --head HEAD and git diff --check upstream/main..HEAD — clean.

Hosted relinker (Ubuntu/Windows), relinker-asan and Linux register-context checks pass on this head; the macOS jobs are still queued. The linux/windows full product builds are skipped for pull requests by the build gate and require a manual workflow dispatch, so the relinker build above is the local product-build evidence available to me. No game was run.

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 3965 docs/dev/debt/libc.md
PR 5021 docs/dev/debt/libc.md
PR 5303 docs/dev/debt/libc.md
PR 6819 docs/dev/debt/libc.md
PR 7081 core/libs/prx/libc/src/LocaleSupport.cpp
docs/dev/debt/libc.md
PR 7386 docs/dev/debt/libc.md
PR 7447 docs/dev/debt/libc.md
PR 7544 docs/dev/debt/libc.md
PR 7715 docs/dev/debt/libc.md
PR 7851 docs/dev/debt/libc.md
PR 8150 docs/dev/debt/libc.md
PR 8417 docs/dev/debt/libc.md
PR 8965 docs/dev/debt/libc.md
PR 9087 docs/dev/debt/libc.md
PR 9340 docs/dev/debt/libc.md
PR 9371 docs/dev/debt/libc.md
PR 9447 docs/dev/debt/libc.md
PR 9466 docs/dev/debt/libc.md
PR 9526 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 9677 docs/dev/debt/libc.md
PR 10002 docs/dev/debt/libc.md
PR 10007 docs/dev/debt/libc.md
PR 10113 docs/dev/debt/libc.md
PR 10158 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 10200 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 10226 docs/dev/debt/libc.md
PR 10245 docs/dev/debt/libc.md
PR 10250 docs/dev/debt/libc.md
PR 10253 docs/dev/debt/libc.md
PR 10274 docs/dev/debt/libc.md
PR 10321 docs/dev/debt/libc.md
PR 10328 docs/dev/debt/libc.md
PR 10345 docs/dev/debt/libc.md
PR 10397 docs/dev/debt/libc.md
PR 10405 docs/dev/debt/libc.md
PR 10506 docs/dev/debt/libc.md
PR 10510 docs/dev/debt/libc.md
PR 10512 docs/dev/debt/libc.md
PR 10569 docs/dev/debt/libc.md
PR 10987 docs/dev/debt/libc.md
PR 11109 docs/dev/debt/libc.md
PR 11260 docs/dev/debt/libc.md
PR 11262 docs/dev/debt/libc.md
PR 11266 docs/dev/debt/libc.md
PR 11332 docs/dev/debt/libc.md
PR 11625 docs/dev/debt/libc.md
PR 11634 docs/dev/debt/libc.md
PR 11661 docs/dev/debt/libc.md
PR 11664 docs/dev/debt/libc.md
PR 11689 docs/dev/debt/libc.md
PR 11698 docs/dev/debt/libc.md
PR 11724 docs/dev/debt/libc.md
PR 11726 docs/dev/debt/libc.md
PR 11831 docs/dev/debt/libc.md
PR 11848 docs/dev/debt/libc.md
PR 11870 docs/dev/debt/libc.md
PR 11895 docs/dev/debt/libc.md
PR 12053 docs/dev/debt/libc.md
PR 12057 docs/dev/debt/libc.md
PR 12184 docs/dev/debt/libc.md
PR 12397 docs/dev/debt/libc.md
PR 12510 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 12511 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 12514 docs/dev/debt/libc.md
PR 12518 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 12530 docs/dev/debt/libc.md
PR 12532 docs/dev/debt/libc.md
PR 12574 docs/dev/debt/libc.md
PR 12592 docs/dev/debt/libc.md
PR 12593 docs/dev/debt/libc.md
PR 12594 docs/dev/debt/libc.md
PR 12598 docs/dev/debt/libc.md
PR 12605 docs/dev/debt/libc.md
PR 12622 docs/dev/debt/libc.md
PR 12627 docs/dev/debt/libc.md
PR 12682 docs/dev/debt/libc.md
PR 12688 docs/dev/debt/libc.md
PR 12700 docs/dev/debt/libc.md
PR 12704 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 12849 docs/dev/debt/libc.md
PR 12920 docs/dev/debt/libc.md
PR 12947 docs/dev/debt/libc.md
PR 12965 docs/dev/debt/libc.md
PR 13390 docs/dev/debt/libc.md
PR 13449 docs/dev/debt/libc.md
PR 13486 docs/dev/debt/libc.md
PR 13794 docs/dev/debt/libc.md
PR 13804 docs/dev/debt/libc.md
PR 13809 docs/dev/debt/libc.md
PR 13828 docs/dev/debt/libc.md
PR 14020 docs/dev/debt/libc.md
PR 14022 core/libs/prx/libc/src/LocaleSupport.cpp
PR 14085 docs/dev/debt/libc.md
PR 14212 docs/dev/debt/libc.md
PR 14298 docs/dev/debt/libc.md
PR 14326 docs/dev/debt/libc.md
PR 14373 core/libs/prx/libc/src/LocaleSupport.cpp
PR 14588 docs/dev/debt/libc.md
PR 14595 docs/dev/debt/libc.md
PR 14610 docs/dev/debt/libc.md
PR 14915 docs/dev/debt/libc.md
PR 15095 docs/dev/debt/libc.md
PR 15199 docs/dev/debt/libc.md
PR 15206 docs/dev/debt/libc.md
PR 15236 docs/dev/debt/libc.md
PR 15336 docs/dev/debt/libc.md
PR 15471 docs/dev/debt/libc.md
PR 15484 docs/dev/debt/libc.md
PR 15486 docs/dev/debt/libc.md
PR 15490 docs/dev/debt/libc.md
PR 15501 docs/dev/debt/libc.md
PR 15519 docs/dev/debt/libc.md
PR 15535 docs/dev/debt/libc.md
PR 15552 docs/dev/debt/libc.md
PR 15561 docs/dev/debt/libc.md
PR 15602 docs/dev/debt/libc.md
PR 15614 docs/dev/debt/libc.md
PR 15667 docs/dev/debt/libc.md
PR 15683 docs/dev/debt/libc.md
PR 15692 core/libs/prx/libc/src/LocaleSupport.cpp
PR 15712 core/libs/prx/libc/src/LocaleSupport.cpp
PR 15713 docs/dev/debt/libc.md
PR 15714 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 15715 core/libs/prx/libc/src/LocaleSupport.cpp
PR 15768 docs/dev/debt/libc.md
PR 15773 docs/dev/debt/libc.md
PR 15778 core/libs/prx/libc/src/LocaleSupport.cpp
core/libs/tests/GuestLocale.cpp
docs/dev/debt/libc.md
PR 15791 docs/dev/debt/libc.md
PR 15796 docs/dev/debt/libc.md
PR 15800 docs/dev/debt/libc.md
PR 15801 docs/dev/debt/libc.md
PR 15802 docs/dev/debt/libc.md
PR 15803 docs/dev/debt/libc.md
PR 15804 docs/dev/debt/libc.md
PR 15807 docs/dev/debt/libc.md
PR 15809 core/libs/prx/libc/src/LocaleSupport.cpp
docs/dev/debt/libc.md
PR 15834 docs/dev/debt/libc.md
PR 15879 docs/dev/debt/libc.md
PR 15923 core/libs/prx/libc/src/LocaleSupport.cpp
PR 15973 docs/dev/debt/libc.md
PR 16004 docs/dev/debt/libc.md
PR 16017 docs/dev/debt/libc.md
PR 16083 core/libs/prx/libc/src/LocaleSupport.cpp
docs/dev/debt/libc.md
PR 16084 docs/dev/debt/libc.md
PR 16104 docs/dev/debt/libc.md

@MarcZX10

Copy link
Copy Markdown
Contributor

Follow-up to my review: the outstanding macOS Intel Debug register-context check has now passed. Linux/macOS/Windows relinker, relinker-ASan, Ubuntu Debug/Release and macOS Intel Debug/Release register-context, and both macOS write-watch jobs pass. Full Linux and Windows product jobs are skipped by the path policy; they are not build results for this change.

@wachi35676

Copy link
Copy Markdown
Contributor

Windows run of head 6ad55bff263c merged onto main 90f918fa7. Windows 11 10.0.26300, WinLibs GCC 15.2.0, Release.

AI-assisted: yes (Claude Code); results above were run on this machine.

@oneandonlydean oneandonlydean self-assigned this Oct 26, 2026
@00xDisaster

Copy link
Copy Markdown
Contributor Author

@MarcZX10 the build and runtime evidence you asked for is now available on 6ad55bff263c:

  • Local Release build of the relinker target, with relinker_conversion, relinker_game_patch and relinker_executables passing 3/3 at this head.
  • Six focused locale suites passing 6/6, with guest_locale also passing 100 repeated runs.
  • A local ANYPS5_ENABLE_ASAN=ON build of libc and guest_locale_tests, with guest_locale passing, including the 16-byte state paths.
  • wachi35676's independent Windows run above: all six suites pass 2/2, while main's LocaleSupport.cpp aborts the negative control.

All hosted relinker, ASan, register-context and write-watch checks pass; the full Linux/Windows product jobs are skipped by the PR path policy. The change still declares its textual dependency on open #10165 and does not modify that PR. Please let me know if this covers the runtime/build evidence request.

@00xDisaster

Copy link
Copy Markdown
Contributor Author

All hosted checks are green on 6ad55bff26 and the evidence above covers the requested local relinker build, the six locale suites, the 100-run guest_locale repeat, the ASan build, and wachi35676's independent Windows run. #10165 remains the declared dependency and is still open; no code changed since your review. Could you approve this head if the evidence is sufficient?

@maskym

maskym commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Windows result for head 6ad55bff26, merged into main 2ee8e9751a (the PR's Tested section names no Windows run).

Host: Windows 11 26300, Intel i7-12700K, WinLibs GCC 15.2.0 (x86_64-ucrt-posix-seh, r6), Release, BUILD_TESTING=ON, Ninja. Build clean.

The tree also carried the open PRs #10780, #10729, #11614, #10631, #10582, #11547, #11584, #11572, all merged cleanly, so the run is a joint one; the tests of this PR are guest_locale. Together with the whole libc, CesCs, Font, FreeType, LibreSsl3 and NpUniversalDataSystem suites those tests belong to: 160/160 passed, this PR's in 0.05 s; the AudioOut suite separately 21/21. Not run on a PS5.

AI-assisted: yes (Claude Code), the runs and the numbers above are from this machine.

@00xDisaster

Copy link
Copy Markdown
Contributor Author

@MarcZX10 @maskym I added the independent Windows result to Tested: guest_locale passed in the 160/160 libc/CesCs/Font/FreeType/LibreSsl3/NpUniversalDataSystem run. The local relinker build, six locale suites, ASan run and wachi35676 Windows run are still the build/runtime evidence; #10165 remains the textual dependency. Could you approve this head if that evidence is sufficient?

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — new head, changes still requested

The independent Windows guest_locale result is helpful, but both the PR and that result use base 74ac0e7912, while current main changed the locale implementation, tests, and debt file.

What I ran

  • Reviewed exact PR head 6ad55bff26 against current main edf6804cf52c62eacafc592dd6142cb4efe5bd05.
  • Ran git merge-base, git merge-tree --write-tree, git diff --name-status for shared paths, and git diff --check.
  • Checked current hosted workflow results. I did not execute locale tests locally.

Results

Check Result
PR base / current main 74ac0e7912 / edf6804cf5
Merge preview Clean; tree 7dbdf8329a4897de163318daeca6595e2599c8e9
Current-main changes on PR paths LocaleSupport.cpp, GuestLocale.cpp, and docs/dev/debt/libc.md
Diff check Passed; no output
Hosted conventions, labels, eligibility, report, relinker, ASan, register-context, write-watch Passed
Hosted product Windows/Linux jobs Skipped
Author-reported Windows result guest_locale passes as part of the 160-test locale/library suite on the PR head, but its integration base predates current main
Unedited available command output
$ git merge-base upstream/main refs/review/upstream-11172
74ac0e7912a5eaa453fff872f4d4fe803154b08c
$ git merge-tree --write-tree upstream/main refs/review/upstream-11172
7dbdf8329a4897de163318daeca6595e2599c8e9
$ git diff --name-status 74ac0e7912..upstream/main -- core/libs/prx/libc/src/LocaleSupport.cpp core/libs/tests/GuestLocale.cpp docs/dev/debt/libc.md
M core/libs/prx/libc/src/LocaleSupport.cpp
M core/libs/tests/GuestLocale.cpp
M docs/dev/debt/libc.md
$ git diff --check upstream/main...refs/review/upstream-11172

$ gh pr checks 11172 -R boykopovar/AnyPS5
conventions	pass	38s
eligibility	pass	4s
labels	pass	9s
register-context (macos-15-intel, Debug)	pass	1m18s
register-context (macos-15-intel, Release)	pass	1m5s
register-context (ubuntu-latest, Debug)	pass	28s
register-context (ubuntu-latest, Release)	pass	25s
relinker (macos-latest, clang++)	pass	3m40s
relinker (macos-latest, clang++, x86_64)	pass	2m34s
relinker (ubuntu-latest, g++)	pass	3m39s
relinker (windows-latest, g++)	pass	4m32s
relinker-asan	pass	2m23s
write-watch (macos-15)	pass	36s
linux	skipping	0
windows	skipping	0
report	pass	31s
write-watch (macos-15-intel)	pass	1m4s

Negative control

Check Result
New test against current-main base Not run; the available author result is for the earlier base

Findings

Blocking

  • Please rebase on current main and rerun guest_locale on the exact refreshed base and head. Main changed the locale implementation and the shared regression test since 74ac0e7912, so the earlier result does not verify the current integration.

Non-blocking

  • None found in the clean merge preview.

Sources

Not verified

  • The exact-head locale result after integrating current main.

To get this to a good state

  • Refresh the branch, run and report guest_locale on current base and change, and update the exact commit hashes in the description.

@00xDisaster
00xDisaster force-pushed the feat/libc-codecvt-wide-vtable branch from 6ad55bf to fdc62fb Compare October 29, 2026 11:22
@00xDisaster

Copy link
Copy Markdown
Contributor Author

@MarcZX10 refreshed onto current main (49025cb436); the new head is fdc62fb1048cd66e6969b1e4819f53d979ec1ca3. I resolved the LocaleSupport.cpp, GuestLocale.cpp and libc.md changes by keeping the current main locale code and the adjacent numpunct/narrow-codecvt changes. On the refreshed head I rebuilt guest_locale, guest_multibyte_locale, guest_wide_formatting, guest_wide_strings, guest_wide_conversion and guest_wide_stream_scan; all 6 pass. Conventions and git diff --check are clean. The body now records the refreshed base/head and notes the Windows result predates the refresh. Could you re-check this head?

@XairRrR XairRrR left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — approved

The refreshed head merges cleanly into current main, builds, passes the six locale suites, and the new guest_locale checks fail against main's LocaleSupport.cpp. I found nothing blocking.

What I ran

Head fdc62fb1048cd66e6969b1e4819f53d979ec1ca3 merged with --no-ff into main ba5b5330b37724bca4b99f30faab504653635a04 in a clean worktree. Release, GCC 16.2.1, Ninja, BUILD_TESTING=ON. Arch Linux 7.2.11-zen, Intel Core i9-14900KF.

git merge --no-ff --no-edit refs/review/11172
git diff --check origin/main...refs/review/11172
python3 tools/check_conventions.py --base origin/main
cmake --build build -j10 --target guest_locale_tests guest_multibyte_locale_tests guest_wide_conversion_tests guest_wide_formatting_tests guest_wide_string_tests guest_wide_stream_scan_tests libc
cmake --build build -j10 --target libs
ctest --test-dir build -j4 -R '^(guest_locale|guest_multibyte_locale|guest_wide_formatting|guest_wide_strings|guest_wide_conversion|guest_wide_stream_scan)$' --output-on-failure
# negative control
git checkout origin/main -- core/libs/prx/libc/src/LocaleSupport.cpp
cmake --build build -j10 --target guest_locale_tests
ctest --test-dir build -R '^guest_locale$' --output-on-failure
git checkout HEAD -- core/libs/prx/libc/src/LocaleSupport.cpp

Results

Check Result
Merge into current main Clean
git diff --check No output
check_conventions.py All conventions checks passed.
Build of the six locale test targets and libc Passed
Build of libs Passed (1941/1941)
Six focused locale suites 6/6 passed
Negative control (guest_locale against main's LocaleSupport.cpp) Fails as expected
ctest, merged tree
1/6 Test #525: guest_multibyte_locale ...........   Passed    0.00 sec
2/6 Test #526: guest_wide_conversion ............   Passed    0.00 sec
3/6 Test #522: guest_wide_formatting ............   Passed    0.00 sec
4/6 Test #659: guest_locale .....................   Passed    0.00 sec
5/6 Test #523: guest_wide_strings ...............   Passed    0.00 sec
6/6 Test #566: guest_wide_stream_scan ...........   Passed    0.00 sec

100% tests passed out of 6

MarcZX10's blocking item on 6ad55bff26 asked for a rebase and a rerun of guest_locale on current main. This head is rebased, and the run above is on the merge with current main ba5b5330b3, so that item is resolved.

Negative control

I restored only core/libs/prx/libc/src/LocaleSupport.cpp from origin/main and kept the PR's GuestLocale.cpp. After a rebuild, guest_locale aborted with Subprocess aborted (the test's Guest locale check failed). With the merged file restored, it passes again.

ctest, negative control
1/1 Test #659: guest_locale .....................Subprocess aborted***Exception:   0.08 sec
0% tests passed, 1 tests failed out of 1
The following tests FAILED:
	659 - guest_locale (Subprocess aborted)

Findings

Blocking

None.

Non-blocking

  • _Mbtowcx still throws where the description says the console returns a code. See LocaleSupport.cpp:864-871. The description says the console's in delegates to _Mbtowcx and maps its results to partial and error. If so, the console's _Mbtowcx returns -2 for incomplete input and -1 for invalid input instead of aborting. The PR now routes _Mbtowcx through the guest helper, but it still throws on both results. The new tests at GuestLocale.cpp:244-253 lock in the throws for "\xe2", a four-byte lead and "\xc3\x28". The port's in calls mbrtowc_nid_postfix directly, so the facet is unaffected, but a guest that calls _Mbtowcx on a split UTF-8 sequence will abort. The throws were already there before this PR, and docs/dev/debt/libc.md does not list them. Suggested fix: if the PPSA03446 disassembly confirms the codes, return -2 and -1 as the console does and assert those values in the test. Otherwise, add a debt entry for the throwing paths. This can be a follow-up.
  • length returns a character count. WideCodecvtLength returns the number of wide characters, and the test expects 3 for six bytes of input (GuestLocale.cpp:93). The standard do_length returns the number of bytes consumed. Older Dinkumware libraries did count characters, so this may well match the console. The debt entry says "counts characters", but it does not say that this differs from the standard. One sentence there, stating that the console behaviour was confirmed, would keep someone from "fixing" it to return bytes later.
  • Depends on: #10165. The description calls this dependency textual only, and the PR merges and passes cleanly on current main without #10165. Listing it under Depends on may hold this PR back behind an open PR it does not need. Consider none, and keep the rebase note in the text.

Not verified

  • Console behaviour: slot order, the max_length value of 6, partial versus ok when in fills the output after converting some characters, and the character-count length. I have no PPSA03446 libc.prx disassembly to compare against.
  • A Windows build or run (16-bit host wchar_t paths). I ran on Linux only.
  • An ASan build.

@00xDisaster
00xDisaster force-pushed the feat/libc-codecvt-wide-vtable branch from fdc62fb to c5f4351 Compare October 30, 2026 22:56
@00xDisaster

Copy link
Copy Markdown
Contributor Author

@XairRrR thanks for the approval. Head is rebased onto current (). The six locale suites still pass 6/6 with the bundled Khronos validation-layer run; the new debt sentence notes that no console disassembly was available for 's -1/-2 returns or the character-count point you raised. I also changed to because the PR merges and passes on current without #10165. The Windows run remains Xair's independent evidence plus maskym's earlier result.

Could you re-check this fresh head? The diff is otherwise the same codecvt implementation and tests.

@00xDisaster
00xDisaster requested a review from MarcZX10 October 30, 2026 23:13

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — changes requested

The new length implementation and test pin a character-count result even though the PR records that the console behavior was not verified.

What I ran

Reviewed exact head c5f43513fbc745807c08b1a0d3513b476ab8c16e against PR base b44985a3ea80f1e9618f7d925292229bf8f051a7. The individual merge preview against current main fc7c353fbcbc974d6b8af027c2769f9f63357b07 was clean. The reported test base 7fcab08f71e463b1768730a626a0f5472d336708 is the merge base of this head and current main; a comparison across the 106 intervening commits found no changes to the locale source, test, debt, or multibyte helper files. Environment: Debian Linux 6.1.0-54-amd64, x86-64, Python 3.11.2; no compiler or project build was run.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 11172
gh pr checks 11172 --repo boykopovar/AnyPS5
python3 tools/pr_stack_check.py 11172 --repo boykopovar/AnyPS5
git merge-base 7fcab08f71e463b1768730a626a0f5472d336708 c5f43513fbc745807c08b1a0d3513b476ab8c16e
git fetch --no-tags https://github.com/boykopovar/AnyPS5.git refs/heads/main
gh api repos/boykopovar/AnyPS5/compare/7fcab08f71e463b1768730a626a0f5472d336708...fc7c353fbcbc974d6b8af027c2769f9f63357b07 --jq '[.files[].filename] | map(select(test("^(core/libs/prx/libc/src/LocaleSupport\\.cpp|core/libs/tests/GuestLocale\\.cpp|docs/dev/debt/libc\\.md|core/libs/prx/libc/src/Multibyte\\.cpp|core/libs/prx/libc/include/Api\\.hpp)$")))'
curl -fsSL https://raw.githubusercontent.com/cplusplus/draft/d4d6f38143c1b495aa33b2e5de0e0ec2daa173ca/source/text.tex -o /tmp/cppdraft-text.tex
grep -n -A28 -B1 '\\indexlibrarymember{codecvt}{do_length}' /tmp/cppdraft-text.tex

I also inspected the exact-head WideCodecvtLength, its test assertions, the updated debt entry, the precheck's convention warning, and the author-reported test scope.

Results

Check Result
Diff and conventions Diff check passed. Conventions reported 0 errors and one warning: the new debt entry is 1,072 characters and should state the gap first.
Current-main integration Clean individual merge preview. The reported test base is the current merge base, and the changed locale/test/debt paths have no later main changes.
Hosted CI Eligibility, conventions, labels, library-portability, report, Windows, Ubuntu relinker, Ubuntu register-context, and ASan passed. macOS relinker, macOS register-context, and write-watch jobs were pending; Linux product and specialized Linux checks were skipped.
Author-reported tests The PR reports six focused locale suites passing on code commit 230cc7a59d44c2e6e9001fbae32036d466578216, plus an ASan guest_locale run. I did not independently run them. The current head adds a debt-file update after that code commit.
length behavior The test expects length(..., max=2) to return 2 for the six-byte input Aé€, and max=4 to return 3. The pinned C++ draft defines the result as the number of external characters consumed and specifies the state effect as if do_in were called. The PR's debt entry says the console length behavior was not disassembled.
Local build or tests Not run.
Unedited output from relevant checks

Precheck convention output:

docs/dev/debt/libc.md:238: warning: [debt-length] Technical debt entry over 1000 characters: state the gap first (what differs from the console, what is unverified, what throws) and keep only the behaviour it needs: 1072 characters
1 findings, 0 errors; GitHub shows at most 10 error annotations, the job summary lists all

Precheck aggregate result:

Conclusion: checks failed

The precheck's ABI and test-quality helpers were unavailable in its isolated snapshot (tools/pr_abi_audit.py and tools/pr_test_quality.py were not present there); those helper failures do not establish a PR defect. The source and test were inspected directly.

Stack preview:

# PR stack check — fresh

Target: https://github.com/boykopovar/AnyPS5/pull/11172
Target branch tip: `fc7c353fbcbc974d6b8af027c2769f9f63357b07`
All heads unchanged: **True**
Dependency order: #11172

## Individual merge previews

- PR #11172: **clean** against current base; head `c5f43513fbc745807c08b1a0d3513b476ab8c16e`; changed paths: none reported

## Dependency relationships

No declared PR dependencies were found in the target PR chain.

Hosted checks:

linux	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356578490
relinker-asan	pass	2m31s	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577141
register-context (macos-15-intel, Debug)	pending	0	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577079
relinker (macos-latest, clang++, x86_64)	pending	0	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577358
register-context (ubuntu-latest, Debug)	pass	33s	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577183
register-context (ubuntu-latest, Release)	pass	29s	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577062
relinker (windows-latest, g++)	pass	6m38s	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577186
labels	pass	8s	https://github.com/boykopovar/AnyPS5/actions/runs/41141412689/job/124358585825
library-portability	pass	1m45s	https://github.com/boykopovar/AnyPS5/actions/runs/41141416046/job/124356311224
conventions	pass	19s	https://github.com/boykopovar/AnyPS5/actions/runs/41141412567/job/124356304483
relinker (ubuntu-latest, g++)	pass	4m15s	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577235
relinker (macos-latest, clang++)	pending	0	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577245
register-context (macos-15-intel, Release)	pending	0	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577203
write-watch (macos-15-intel)	pending	0	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577152
write-watch (macos-15)	pending	0	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577069
eligibility	pass	10s	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356311738
report	pass	1m0s	https://github.com/boykopovar/AnyPS5/actions/runs/41141415992/job/124356313581
windows	pass	7m34s	https://github.com/boykopovar/AnyPS5/actions/runs/41141416084/job/124356577045

Findings

Blocking

WideCodecvtLength returns the number of decoded wide characters and leaves the caller's state unchanged by using a local copy. The new test locks in that behavior. The author’s latest comment acknowledges that the character-count behavior is unverified on the console, while the exact-head implementation and tests still assert it. This remains an unmeasured target-specific assertion, and it differs from the standard codecvt::do_length contract. Please either provide pinned binary/console evidence for the target's return value and state behavior and test those results, or leave this slot throwing and record the unresolved behavior until it is verified, as the repository requires for unknown behavior.

Non-blocking

The debt entry exceeds the convention's 1,000-character guidance and the checker asks that it lead with the unresolved gap. This is a warning, not a check failure.

Sources

Not verified

I did not build or run C++ tests locally or test on a PS5. The six focused suite results and ASan run are author-reported; the current hosted macOS jobs were still pending when checked.

To get this to a good state

Please verify length against the pinned target binary or console, or keep this slot unsupported until its behavior is known. I will rerun the relevant checks against the new head.

The wide codecvt data object added by boykopovar#10180 was still thirteen zeroed slots. Fill slots 2 through 12 with the facet methods and the seven conversion virtuals: always_noconv is false, max_length is 6, encoding is 0, in and out convert UTF-8 of at most three bytes, unshift clears the state, and length counts characters without changing the caller's state.

The console's wide codecvt virtuals delegate to _Mbtowcx and _Wctombx, so route those exports through the guest UTF-8 helpers instead of the host C locale, and reserve the 16-byte guest conversion state that _Getpmbstate and _Getpwcstate return. Cover the exported object, the conversion results, a partial output buffer, an invalid four-byte lead, the length limit and unshift.
@00xDisaster
00xDisaster force-pushed the feat/libc-codecvt-wide-vtable branch from c5f4351 to 597258f Compare October 31, 2026 20:36
@00xDisaster

Copy link
Copy Markdown
Contributor Author

@MarcZX10 I took the second option: the length slot now throws instead of asserting an unmeasured character count. New head 597258ffad, rebased onto current main 0836dfdf4f.

  • WideCodecvtLength only throws codecvt<wchar_t,char>::length: console behavior unverified; it no longer decodes input, copies the state or returns a count.
  • guest_locale now calls the exported slot through the vtable and asserts that it throws, instead of pinning 2 and 3 for Aé€.
  • The debt entry leads with the gap, says the slot throws, and is 965 characters, below the 1,000-character guidance.

The rest of the vtable is unchanged: in, out and unshift remain wired and the 6 locale suites pass after the rebase:

  • cmake --build build --target guest_locale_tests guest_multibyte_locale_tests guest_wide_conversion_tests guest_wide_formatting_tests guest_wide_string_tests guest_wide_stream_scan_tests -j$(nproc): passed.
  • ctest --test-dir build -R '^(guest_locale|guest_multibyte_locale|guest_wide_formatting|guest_wide_strings|guest_wide_conversion|guest_wide_stream_scan)$' --output-on-failure: 6/6 passed.
  • Conventions and git diff --check are clean.

One CI note: both macOS write-watch jobs fail at configure with duplicate write_watch_execute-fault/write_watch_read-fault test names. core/libs/tests/write_watch/CMakeLists.txt contains that loop twice on upstream/main as well, and this PR does not touch the file, so the failure is on the base branch rather than this change.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Reviewed at 597258ffad. Leaving the unmeasured codecvt<wchar_t,char>::length operation unsupported and recording that limit in debt is fine.

Please remove the new RequireException assertion that calls vtable->length with the valid Aé€ input. Tests must not require an unimplemented operation to throw, since that assertion breaks when the operation is implemented. Keep the positive in, out, unshift, state and malformed-argument checks. No implementation of length is requested here.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 1, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head fcb412c merged onto main 291e02d · tested 2026-11-01 14:15 UTC · 12 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 3,042 passed · 14 failed (0 new, 13 also fail on main, 1 unstable on main) · 57 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 3,113 of 3,155 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (1226 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_graphics 88.5 s, ⚠️ agc_driver_graphics_maps_fallback 88.5 s, ⚠️ agc_driver_bda_device 55.2 s, ⚠️ agc_driver_sample_multisample_target 42.9 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 3 of the last 4 main runs
Failing on main too (13, not counted against this PR)
agc_driver_guest_memory_lifetime_direct
agc_driver_image_table
agc_driver_job_manager_compute_capacity
agc_driver_native_depth_bda_clear
agc_driver_native_depth_buffer_clear
agc_driver_native_depth_clears
agc_driver_native_multisample_depth
agc_driver_submit_progress
agc_idle_publish_wait
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (5 IDs in 711 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (711 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, and 703 more
VUID-vkCmdCopyImage-srcImage-01548 (11 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_storage_dispatch, and 3 more
VUID-vkCmdCopyImage-srcImage-01551 (11 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_storage_dispatch, and 3 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (57)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_copied_writer_label_order_drain: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not 
Reproduce
git fetch origin fcb412c6d9f552e5f4f8bd22f23810bd76e41af8 291e02d4877784d03d346962af51713b9df63b91
git checkout 291e02d4877784d03d346962af51713b9df63b91 && git merge --no-ff fcb412c6d9f552e5f4f8bd22f23810bd76e41af8
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 1, 2026
# Conflicts:
#	core/libs/prx/libc/src/LocaleSupport.cpp
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Nov 2, 2026
@maskym

maskym commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Retested head d7562dcc1d on Windows (its own commits changed since my earlier run), merged alone into main a4eca2a056.

Host: Windows 11 26300, Intel i7-12700K, WinLibs GCC 15.2.0 (x86_64-ucrt-posix-seh, r6), Release, BUILD_TESTING=ON, Ninja. Build clean.

guest_locale: 1/1 pass, three runs. Not run on a PS5.

AI-assisted: yes (Claude Code), the runs and the numbers above are from this machine.

@XairRrR XairRrR left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — approved

Since fdc62fb104, the length slot throws instead of returning an unverified character count, the debt entry records that gap, and the checklist now reads Depends on: none. The merged tree builds, the six locale suites pass, and guest_locale still fails against main's LocaleSupport.cpp.

What changed since my last review

  • 597258ffad: WideCodecvtLength now only throws (codecvt<wchar_t,char>::length: console behavior unverified). The test no longer expects 2/3 for Aé€; it now requires the slot to throw.
  • 6d06d26606: the debt entry leads with the length gap, names PPSA03446's libc.prx as the source of the layout and of the _Mbtowcx/_Wctombx delegation, and notes that offset-to-top and typeinfo stay zero.
  • Two merge commits from main resolve conflicts in docs/dev/debt/libc.md and LocaleSupport.cpp. The in/out/unshift code and its tests are unchanged.
  • Description: Depends on: none (previously #10165), and a new Windows rerun by maskym on d7562dcc1d (guest_locale passed 3 runs; author-reported).
  • Discussion: MarcZX10 asked for length to throw until it is measured, which is now done. oneandonlydean then asked for the RequireException on length to be removed from the test; that has not been done (see below).

What I ran

Head d7562dcc1d873ad19809c9b31d350de94db517c9 merged with --no-ff into main 096c45570f516de76a43bbe1b97781381c84f55f (merged tree 4d8e99a644e1bb9ff664b93f011e943a152cd705). Debian 13 VM, GCC 14.2.0, Release, Ninja, BUILD_TESTING=ON.

git diff --check 096c45570f516de76a43bbe1b97781381c84f55f...d7562dcc1d873ad19809c9b31d350de94db517c9
python3 tools/check_conventions.py --base 096c45570f516de76a43bbe1b97781381c84f55f
ctest --test-dir build -R '^(guest_locale|guest_multibyte_locale|guest_wide_formatting|guest_wide_strings|guest_wide_conversion|guest_wide_stream_scan)$' --output-on-failure
# negative control
git show 096c45570f516de76a43bbe1b97781381c84f55f:core/libs/prx/libc/src/LocaleSupport.cpp > core/libs/prx/libc/src/LocaleSupport.cpp
ninja -C build guest_locale_tests
ctest --test-dir build -R '^guest_locale$' --output-on-failure
git show 4d8e99a644e1bb9ff664b93f011e943a152cd705:core/libs/prx/libc/src/LocaleSupport.cpp > core/libs/prx/libc/src/LocaleSupport.cpp
ninja -C build guest_locale_tests
ctest --test-dir build -R '^guest_locale$'
git status --porcelain
Check Result
git diff --check No output
check_conventions.py All conventions checks passed.
Build and libs (script) Passed
Selected tests (script, 3496) No new failures and no timeouts. The 9 known failures also fail on main (none are locale tests)
Six locale suites 6/6 passed
Negative control guest_locale aborts with main's LocaleSupport.cpp and passes again with the merged file restored. The worktree is clean afterwards
ctest, negative control
0% tests passed, 1 tests failed out of 1
The following tests FAILED:
	797 - guest_locale (Subprocess aborted)

Previous findings

  • length returns a character count: Resolved. WideCodecvtLength now throws. The debt entry states that the return value and state effect are unverified and that the standard do_length consumes input bytes. This also answers MarcZX10's blocking item on c5f43513fb.
  • Depends on: #10165: Resolved. The checklist now reads none, and the description keeps the textual rebase note. The PR merges and passes on current main without #10165.
  • _Mbtowcx throws on incomplete or invalid input: Still open, non-blocking. LocaleSupport.cpp:932-937 still throws on the -1 and -2 results. GuestLocale.cpp:243-252 still asserts those throws. The debt entry says in/out delegate to _Mbtowcx/_Wctombx on the console, which suggests the console returns codes there, but it does not list the throwing paths. Suggested fix: add the throws to the debt entry, or return the console's codes once they are confirmed. This can be a follow-up.

New findings

Blocking

None.

Non-blocking

  • The test requires the unimplemented length slot to throw. At GuestLocale.cpp:92, RequireException([&] { vtable->length(...); }) is still present at this head, although oneandonlydean asked on 597258ffad for it to be removed. Whoever later implements length would have to delete it. I agree with their request: drop that line and keep the positive in/out/unshift checks and the state checks. This is not blocking because no written rule in CONTRIBUTING.md or AGENTS.md forbids it.

Not verified

  • Console behaviour of the slot order, max_length 6, the partial/error mapping and length. I have no PPSA03446 libc.prx disassembly.
  • Windows (16-bit wchar_t) and ASan runs. Both are author- or contributor-reported only (maskym's Windows rerun on d7562dcc1d; the author's ASan run on an earlier head).
  • Validation-layer comparison: not applicable, because the change touches no AGC driver, shader recompiler or VideoOut file.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 4, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head d7562dc merged onto main b11c7bf · tested 2026-11-04 18:31 UTC · 28 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 3,768 passed · 15 failed (0 new, 13 also fail on main, 2 unstable on main) · 62 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 3,845 of 3,894 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (1448 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.6 s, ⚠️ agc_driver_graphics_maps_fallback 113.7 s, ⚠️ agc_driver_graphics 113.4 s, ⚠️ public_headers 88.1 s, ⚠️ agc_driver_bda_device 46.5 s
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 8 of the last 10 main runs
agc_driver_two_sample_alpha_to_coverage_sample_mask_export: failed in 3 of the last 10 main runs
Failing on main too (13, not counted against this PR)
agc_driver_alpha_to_coverage_sample_mask_export
agc_driver_guest_memory_lifetime_direct
agc_driver_image_table
agc_driver_job_manager_compute_capacity
agc_driver_native_depth_bda_clear
agc_driver_native_depth_buffer_clear
agc_driver_native_depth_clears
agc_driver_native_multisample_depth
agc_driver_submit_progress
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Passed on retry (1, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)
public_headers_compile_15: Timeout in the parallel run
Validated but not compared (64, not in the main baseline's validation pass)
public_headers
public_headers_compile_0
public_headers_compile_1
public_headers_compile_10
public_headers_compile_11
public_headers_compile_12
public_headers_compile_13
public_headers_compile_14
public_headers_compile_15
public_headers_compile_16
public_headers_compile_17
public_headers_compile_18
public_headers_compile_2
public_headers_compile_20
public_headers_compile_21
public_headers_compile_22
public_headers_compile_23
public_headers_compile_24
public_headers_compile_25
public_headers_compile_26
public_headers_compile_27
public_headers_compile_28
public_headers_compile_29
public_headers_compile_3
public_headers_compile_30
public_headers_compile_31
public_headers_compile_32
public_headers_compile_33
public_headers_compile_34
public_headers_compile_35
public_headers_compile_36
public_headers_compile_37
public_headers_compile_38
public_headers_compile_39
public_headers_compile_4
public_headers_compile_40
public_headers_compile_41
public_headers_compile_42
public_headers_compile_43
public_headers_compile_44
public_headers_compile_45
public_headers_compile_46
public_headers_compile_47
public_headers_compile_48
public_headers_compile_49
public_headers_compile_5
public_headers_compile_50
public_headers_compile_51
public_headers_compile_52
public_headers_compile_53
public_headers_compile_54
public_headers_compile_55
public_headers_compile_56
public_headers_compile_57
public_headers_compile_58
public_headers_compile_59
public_headers_compile_6
public_headers_compile_60
public_headers_compile_61
public_headers_compile_62
public_headers_compile_63
public_headers_compile_7
public_headers_compile_8
public_headers_compile_9
Validation IDs already present on main (8 IDs in 800 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (800 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_draw_space_reuse_held, agc_driver_address_draw_space_reuse_off, agc_driver_address_draw_space_reuse_transitions, agc_driver_address_draw_space_reuse_verify, agc_driver_address_passes, and 792 more
VUID-vkCmdCopyImage-srcImage-01548 (11 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store_image_copy, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_partially_unmapped_plane, agc_driver_depth_plane_unmapped_plane, and 3 more
VUID-vkCmdCopyImage-srcImage-01551 (11 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store_image_copy, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_partially_unmapped_plane, agc_driver_depth_plane_unmapped_plane, and 3 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
VUID-VkSamplerCreateInfo-addressModeU-01079 (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeU-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeV-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeW-parameter (1 test): agc_driver_image_gather_volume
Skipped (62)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_copied_writer_label_order_drain: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_float16_unused_nan_payloads: skipped, the device has no native f16 conversions with RTE rounding and kept f16 denormals
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_idle_publish_wait: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a forced watch of the import reads its submissions as CPU stores
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_storage_pending_key_refresh: skipped, refreshes over a pending key store are not testable here
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergp
Reproduce
git fetch origin d7562dcc1d873ad19809c9b31d350de94db517c9 b11c7bf84f5d2f636ff60166cc3371bd071e24d5
git checkout b11c7bf84f5d2f636ff60166cc3371bd071e24d5 && git merge --no-ff d7562dcc1d873ad19809c9b31d350de94db517c9
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs libc needs rebase Conflicts with main, rebase needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants